/**
 * @file RuneDetector.cpp
 * @author 刘晨光 (Ermaotie@163.com)
 * @brief 
 * @version 0.1
 * @date 2021-09-30
 * 
 * @copyright Copyright (c) 2021
 * 
 */
#include "RuneDetector.h"

/**
 * @brief 运行
 * 
 */
void RuneDetector::run()
{
    VideoCapture cap(video_path);
    while (cap.read(src))
    {
        split(src, channels);
        /**
         * @brief 强化蓝色通道
         * 
         */
        b_channel = channels[0] * 1.5 - channels[1] - channels[2];
        threshold(b_channel, threshold_mask, thresh, 255, THRESH_BINARY);

        /**
         * @brief 形态学闭运算，使的小箭头连接在一起，减少轮廓数量，方便后续提取子轮廓
         * 
         */
        Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
        morphologyEx(threshold_mask, threshold_mask, MORPH_CLOSE, element);

        findContours(threshold_mask, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

        /**
         * @brief 记录每个轮廓的子轮廓个数
         * 
         */
        int contour[20] = {0};
        for (int i = 0; i < contours.size(); i++)
        {
            if (hierarchy[i][3] != -1)
            {
                contour[hierarchy[i][3]]++;
            }
        }

        Point2i center;
        /**
         * @brief 找出仅有一个子轮廓的轮廓
         * 
         */
        for (int j = 0; j < contours.size(); j++)
        {
            if (contour[j] == 1)
            {
                int num = hierarchy[j][2];
                RotatedRect box = minAreaRect(contours[num]);
                if (box.size.height / box.size.width < 2 && box.size.height / box.size.width > 0.5f) // 长宽比防止误判
                {
                    Point2f vertex[4];
                    box.points(vertex);
                    // 画出区域及中点
                    for (int i = 0; i < 4; i++)
                    {
                        line(src, vertex[i], vertex[(i + 1) % 4], line_color, 2);
                    }
                    center = (vertex[0] + vertex[2]) / 2;
                    circle(src, center, 2, point_color, 2);
                }
            }
        }
        namedWindow("Result", WINDOW_AUTOSIZE);
        imshow("Result", src);
        waitKey(delay);
    }
}

/**
 * @brief 读取 config.yaml 的数据
 * 
 * @param config_path 
 */
RuneDetector::RuneDetector(String config_path)
{
    FileStorage fread(config_path, FileStorage::READ);
    fread["video_path"] >> video_path;
    fread["line_color"][0] >> line_color[0];
    fread["line_color"][1] >> line_color[1];
    fread["line_color"][2] >> line_color[2];
    fread["point_color"][0] >> point_color[0];
    fread["point_color"][1] >> point_color[1];
    fread["point_color"][2] >> point_color[2];
    fread["delay"] >> delay;
    fread["thresh"] >> thresh;
}
